/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.bitoon.basketdudes.ws;

import com.bitoon.basketdudes.jpa.Elo;
import com.bitoon.basketdudes.jpa.Equipo;
import com.bitoon.basketdudes.jpa.RankingAcumulado;
import com.bitoon.basketdudes.jpa.RankingAcumuladoV;
import com.bitoon.basketdudes.jpa.RankingDivision;
import com.bitoon.basketdudes.jpa.RankingElo;
import java.io.IOException;
import java.io.PrintWriter;
import java.math.MathContext;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.Query;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.FactoryConfigurationError;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.apache.log4j.Logger;
import org.jdom.output.XMLOutputter;
import org.w3c.dom.DOMImplementation;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.Element;

/**
 *
 * @author paco
 */
public class XMLCreator {
    private static final String CONTENT_TYPE = "text/xml";
    
    Logger log      = Logger.getLogger(Competicion.class);
    
    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
    {
        response.setContentType(CONTENT_TYPE);
        PrintWriter out = response.getWriter();
        JAXPTransformWithDOM(out);

    }
    
    public void JAXPTransformWithDOM(PrintWriter out)
    {
      // Create XML DOM document (Memory consuming).
      Document xmldoc = null;
      try
      {
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        DocumentBuilder builder = factory.newDocumentBuilder();
        DOMImplementation impl = builder.getDOMImplementation();
        Element e = null;
        Node n = null;
        // Document.
        xmldoc = impl.createDocument(null, "USERS", null);
        // Root element.
        Element root = xmldoc.getDocumentElement();
        String[] id = {"PWD122","MX787","A4Q45"};
        String[] type = {"customer","manager","employee"};
        String[] desc = {"Tim@Home","Jack&Moud","John D'oé"};
        for (int i=0;i<id.length;i++)
        {
            // Child i.
            e = xmldoc.createElementNS(null, "USER");
            e.setAttributeNS(null, "ID", id[i]);
            e.setAttributeNS(null, "TYPE", type[i]);
            n = xmldoc.createTextNode(desc[i]);
            e.appendChild(n);
            root.appendChild(e);
        }
    } catch (FactoryConfigurationError e)
    {
        System.out.println("Could not locate a JAXP DocumentBuilderFactory class");
    }
    catch (ParserConfigurationException e)
    {
        System.out.println("Could not locate a JAXP DocumentBuilder class");
    }

    // DOM Transform.
    try
    {
        DOMSource domSource = new DOMSource(xmldoc);
        StreamResult streamResult = new StreamResult(out);
        TransformerFactory tf = TransformerFactory.newInstance();
        Transformer serializer = tf.newTransformer();
        serializer.setOutputProperty(OutputKeys.ENCODING,"ISO-8859-1");
        serializer.setOutputProperty(OutputKeys.DOCTYPE_SYSTEM,"users.dtd");
        serializer.setOutputProperty(OutputKeys.INDENT,"yes");
        serializer.transform(domSource, streamResult);
    } catch (Exception e)
    {
      e.printStackTrace();
    }
    } 
    
    /* 
     * Formatea un XML con las consultas a los tres tipos de ranking
     * 
     * Rendimiento: cada fila recuperada de un ranking implica una consulta del equipo y del usuario y a veces del elo
     * 
     * Solución: cachear cada media hora el contenido de las páginas del ranking
     * 
     * Solución 2: Peor, desnormalizar nombres de equipo y usuario en las tablas de ranking.
     * 
     */
    public void FormateaRanking(EntityManager em, PrintWriter out,int error,
            List<RankingAcumulado> lista1,List<RankingElo> lista2,List<RankingDivision> lista3)
    {
        log.debug("FormateaRankingDivision");        
      // Create XML DOM document (Memory consuming).
      Document xmldoc = null;
      RankWBCStar ranking = new RankWBCStar();
      try
      {
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            DocumentBuilder builder = factory.newDocumentBuilder();
            DOMImplementation impl = builder.getDOMImplementation();
            Element e = null;
            Node n = null;
            // Document.
            xmldoc = impl.createDocument(null, "lista", null);
            // Root element.
            Element root = xmldoc.getDocumentElement();

            e = xmldoc.createElementNS(null, "error");
            e.setAttributeNS(null, "valor"    , Integer.toString(error) );

            if ( lista1 != null ) {
                for (int i=0;i<lista1.size();i++)
                {
                    RankingAcumulado objeto = (RankingAcumulado)lista1.get(i);
                    e = xmldoc.createElementNS(null, "pos");
                    e.setAttributeNS(null, "val"    , Integer.toString(objeto.getPosicion()) );
                    e.setAttributeNS(null, "pto"    , Integer.toString(objeto.getPuntos()));

                    Equipo equipo = BuscarEquipo ( em, objeto.getEquipoId());
                    if (equipo != null) {
                        e.setAttributeNS(null, "equipo" , equipo.getNombre()+" "+equipo.getNick() );
                        e.setAttributeNS(null, "nick"   , equipo.getUsuario().getNick());
                        e.setAttributeNS(null, "id"     , Integer.toString(equipo.getId()));
                    }                    
                    root.appendChild(e);
                }
            } else if (lista2 != null ) {
                for (int i=0;i<lista2.size();i++)
                {
                    RankingElo objeto = (RankingElo)lista2.get(i);
                    e = xmldoc.createElementNS(null, "pos");
                    e.setAttributeNS(null, "val"    , Integer.toString(objeto.getPosicion()) );
                    e.setAttributeNS(null, "elo"    , Integer.toString(objeto.getElo().intValue()));

                    Equipo equipo = BuscarEquipo ( em, objeto.getEquipoId());
                    if (equipo != null) {
                        e.setAttributeNS(null, "equipo" , equipo.getNombre()+" "+equipo.getNick() );
                        e.setAttributeNS(null, "nick"   , equipo.getUsuario().getNick());
                        e.setAttributeNS(null, "id"     , Integer.toString(equipo.getId()));
                    }                    
                    root.appendChild(e);
                }
            } else if (lista3 != null ) {
                for (int i=0;i<lista3.size();i++)
                {
                    RankingDivision objeto = (RankingDivision)lista3.get(i);
                    e = xmldoc.createElementNS(null, "pos");
                    e.setAttributeNS(null, "val"    , Integer.toString(objeto.getPosicion()) );
                    e.setAttributeNS(null, "pto"    , Integer.toString(objeto.getPuntos()));
                    e.setAttributeNS(null, "jugados", Integer.toString(objeto.getGanados()+objeto.getPerdidos()));
                    Equipo equipo = BuscarEquipo ( em, objeto.getEquipoId());
                    if (equipo != null) {
                        e.setAttributeNS(null, "equipo" , equipo.getNombre()+" "+equipo.getNick() );
                        e.setAttributeNS(null, "nick"   , equipo.getUsuario().getNick());
                        e.setAttributeNS(null, "id"     , Integer.toString(equipo.getId()));
                    }
                    RankingElo elo = ranking.BuscarRankingElo ( em, equipo.getId());
                    if ( elo == null ) {
                        e.setAttributeNS(null, "elo"    , "0");
                    } else {
                        e.setAttributeNS(null, "elo"    , Integer.toString( elo.getElo().intValue() ));
                    }
                   
                    root.appendChild(e);
                }                
            }
        } catch (FactoryConfigurationError e) {
            log.error("[Could not locate a JAXP DocumentBuilderFactory class]: " , e);
        } catch (ParserConfigurationException e) {
            log.error("[Could not locate a JAXP DocumentBuilder class]: " , e);
        } catch (Exception e) {
            log.error("[Dom Transform]: " , e);            
        }
        // DOM Transform.
        try {
            
/*            
            doc=new org.jdom.Document(root);//Creamos el documento
            //doc.setDocType(new DocType("text/xml"));
            doc.setDocType(null);
            out=new XMLOutputter();
*/            
            
            DOMSource domSource = new DOMSource(xmldoc);
            StreamResult streamResult = new StreamResult(out);
            TransformerFactory tf = TransformerFactory.newInstance();
            Transformer serializer = tf.newTransformer();
            serializer.setOutputProperty(OutputKeys.ENCODING,"ISO-8859-1");
            //serializer.setOutputProperty(OutputKeys.DOCTYPE_SYSTEM,"ranking.dtd");
            serializer.setOutputProperty(OutputKeys.INDENT,"yes");
            serializer.transform(domSource, streamResult);

        } catch (Exception e) {
          log.error("[Dom Transform]: " , e);
        }
    } 
    
    public Equipo BuscarEquipo( EntityManager em, int p_id ) {
                    
        Query qv = em.createNamedQuery("Equipo.findById");                    
        qv.setParameter("idEquipo", p_id );

        List<Equipo> l = qv.getResultList();
        if ( l.isEmpty() ) {
            return null;
        } else {
            return l.get(0);
        }
    }
    
}
